:- source.
:- assert_static((aleph_random(X):- X is random)).



/*
   Se tienen N ejemplos_positivos+ejemplos_negativos, para un cross-validation de 10 folds, hay que elegir
   10 subconjuntos de N/10, para ello se debe elegir aleatoriamente cada elemento de cada fold.
   Para esta elección creamos un conjunto de N números aleatorios de 1 a N, de esta manera podemos separar los
   10 folds. 
   
   Por ejemplo se tiene una lista de 20 ejemplos (10 negativos y 10 positivos), y queremos 5 folds de 4 ejemplos, primero
   creamos con generate_randoms( 20, Lista), lo cual nos dará por ejemplo una lista com la siguiente
   
   [9,4,7,5,12,17,11,15,1,19,3,14,2,8,20,13,10,16,6,18] entonces los folds se haran eligiendo
   
    Los ejemplos  [9,4,7,5]   [12,17,11,15], [1,19,3,14] [2,8,20,13], [10,16,6,18]
	
	generate_randoms, lo único que hace es revolver la lista de número de ejemplos, despues se hace la elección de los subconjuntos.
	
*/


% aleph_remove_nth(+N,+List1,-Elem,-List2)
%	remove the nth elem from a List
aleph_remove_nth(1,[H|T],H,T):- !.
aleph_remove_nth(N,[H|T],X,[H|T1]):-
        N1 is N - 1,
        aleph_remove_nth(N1,T,X,T1).
		
		
		
% converts an interval-list into a list of (sorted) numbers
intervals_to_list(L,L1):-
	intervals_to_list(L,[],L0),
	sort(L0,L1), !.

intervals_to_list([],L,L).
intervals_to_list([Interval|Intervals],L1,L2):-
	interval_to_list(Interval,L1,L),
	intervals_to_list(Intervals,L,L2).

% converts an interval into a list
interval_to_list(Start-Finish,[]):-
	Start > Finish, !.
interval_to_list(Start-Finish,[Start|T]):-
	Start1 is Start+1,
	interval_to_list(Start1-Finish,T).

% converts an interval into a list
%	with an accumulator list. Result will be in reverse order
interval_to_list(Start-Finish,L,L):-
	Start > Finish, !.
interval_to_list(Start-Finish,L,L1):-
	Start1 is Start+1,
	interval_to_list(Start1-Finish,[Start|L],L1).
     
	 
generate_randoms(Number, FinalList):-
     intervals_to_list([1-Number], List), 
	 generate_randoms2(List, FinalList).
	 
	 
generate_randoms2( [], []  ).

generate_randoms2(List,[Element|SubListFinal]):-
     length(List, Len),     
	 get_random(Len, Number),
	 aleph_remove_nth(Number, List, Element, Sublist),
     generate_randoms2(Sublist, SubListFinal).



pausa :- write('Pulsa <return> para buscar otra solucion'),
         skip(10),nl.
		 
		 

%  ***CON_ESTE_OBTENEMOS EL ELEMENTO N DE UNA LISTA
% Devuelve el N-ésimo elemento de la lista dada en el primer argumento
get_element_from_list([],_N,[]):-!.
get_element_from_list([_X|_Y],1,_X):-!.
get_element_from_list([_X|Y],N,E):-N1 is N - 1,get_element_from_list(Y,N1,E).



% get_random(+Last,-Num)
% 	get a random integer between 1 and Last
get_random(Last,INum):-
	aleph_random(X),
	INum1 is integer(X*Last + 0.5),
	(INum1 = 0 ->
		INum = 1;
		(INum1 > Last ->
			INum = Last;
			INum = INum1
		)
	).
	
	
	
	
	
lista_ejemplos(PredicadoEjemplo, Lista):-
     findall( PredicadoEjemplo, PredicadoEjemplo, Lista),!.
	 

enlista_ejemplos_aleatorios( [], _, []).
	 
enlista_ejemplos_aleatorios( [Aleatorio|Resto], ListaEjemplos, [Ejemplo|ListaEjemplosAleatorios]):-
      aleph_remove_nth(Aleatorio, ListaEjemplos, Ejemplo, _), nl,write(Ejemplo),
	  enlista_ejemplos_aleatorios( Resto, ListaEjemplos, ListaEjemplosAleatorios),!.
	
	
/*
  Pasos para crear los fold
	     1.- llamar al archivo de la lista de los N ejemplos, sólo los ejemplos (hechos).    
		                    Esto con un [NombreArchivoConExtension pl]
							
		 2.- Crear una lista: ListaAleatorios con N numeros aleatorios, donde N es el número de ejemplos totales.
		                    generate_randoms(N, ListaAleatorios).
							
		 3.- Creamos una lista con los ejemplos, p.e. 
		                    lista_ejemplos( no_payment_due(Example, Class), ListaEjemplos).
		 
		 4.- Con las dos listas anteriores, solamente tomamos de ListaEjemplos los elementos conforme a los números aleatorios, 
		     en Lista, que vayan indicando.
			                 enlista_ejemplos_aleatorios( ListaAleatorios, ListaEjemplos, ListaEjemplosAleatorios).
	
	     5.- Una vez obtenida la lista solamente partimos conforme al tamaño del fold.
		 
		 
		 Por ejemplo
		 
		 ?- [generate_randoms].
            % consulting /home/orlando/doctorado/generate_randoms.pl...
            % consulted /home/orlando/doctorado/generate_randoms.pl in module user, 0 msec 8192 bytes
         yes
         ?- [todos_ejemplos].
            % consulting /home/orlando/doctorado/todos_ejemplos.pl...
            % consulted /home/orlando/doctorado/todos_ejemplos.pl in module user, 4 msec 155648 bytes
         yes
         ?- generate_randoms(1000, ListaAleatorios), lista_ejemplos( no_payment_due(E, C), ListaEjemplos), enlista_ejemplos_aleatorios(ListaAleatorios, ListaEjemplos, ListaEjemplosAleatorios).

	
*/	




